package project.view.tag;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import javax.servlet.jsp.JspException;

import online.view.ViewUtil;
import online.view.tag.BaseTag;
import project.common.db.DBColumnInfo;
import project.common.db.DBMetaData;

import common.db.JdbcSource;
import common.db.jdbc.Jdbc;

import core.config.Factory;
import core.exception.ThrowableUtil;

/**
 * コード名称取得クラス
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class MasterNameTag extends BaseTag {
	/** serialVersionUID */
	private static final long serialVersionUID = -1778686011031432028L;

	/** 変数用変数 */
	private String[] var = null;
	/** テーブル */
	private String table = null;
	/** 条件カラム */
	private String[] column = null;
	/** 条件値 */
	private String[] value = null;
	/** 取得項目名 */
	private String[] label = null;

	/**
	 * リリース処理
	 */
	@Override
	public void release() {
		this.var = null;
		this.table = null;
		this.column = null;
		this.value = null;
		this.label = null;
	}

	/**
	 * 変数設定
	 *
	 * @param val 保存変数名文字列
	 */
	public void setVar(final String val) {
		this.var = super.splitValue(val);
	}

	/**
	 * テーブル名
	 *
	 * @param val テーブル名
	 */
	public void setTable(final String val) {
		this.table = val;
	}

	/**
	 * 条件値設定
	 *
	 * @param val 条件値
	 */
	public void setWhereValue(final String val) {
		this.value = super.splitValue(val);
	}

	/**
	 * 名称項目設定
	 *
	 * @param val 名称項目
	 */
	public void setNameColumn(final String val) {
		this.label = super.splitValue(val);
	}

	/**
	 * 条件カラム名設定
	 *
	 * @param val 条件カラム名
	 */
	public void setWhereColumn(final String val) {
		this.column = super.splitValue(val);
	}

	/**
	 * @see javax.servlet.jsp.tagext.TagSupport#doStartTag()
	 */
	@Override
	public int doStartTag() throws JspException {
		try {
			if (this.var != null) {
				for (final String name : this.var) {
					this.pageContext.removeAttribute(name);
				}
			}

			if (this.column == null) {
				return EVAL_PAGE;
			}

			String[] val = getRecordValue(getQuery());
			for (int i = 0; i < val.length; i++) {
				String name = null;
				if (this.var != null && i < this.var.length) {
					name = this.var[i];
				}
				super.output(name, ViewUtil.sanitize(
						val[i], ViewUtil.getCharset(super.getResponse()), true));
			}
			return SKIP_BODY;
		} finally {
			release();
		}
	}

	/**
	 * レコード値取得
	 *
	 * @param query クエリ
	 * @return レコード値
	 * @throws JspException jsp例外
	 */
	private String[] getRecordValue(final String query) throws JspException {
		try (Jdbc conn = JdbcSource.getConnection()) {
			try (PreparedStatement psmt = conn.readonlyStatement(query)) {
				for (int i = 0; i < this.value.length; i++) {
					psmt.setObject(i + 1, this.value[i]);
				}

				try (ResultSet rs = psmt.executeQuery()) {
					if (rs.next()) {
						String[] item = new String[this.label.length];
						for (int i = 0; i < item.length; i++) {
							item[i] = rs.getString(this.label[i]);
						}
						return item;
					}
				}
			}
			return new String[0];
		} catch (SQLException ex) {
			ThrowableUtil.error(ex);
			throw new JspException(ex);
		}
	}

	/**
	 * クエリ取得
	 *
	 * @return クエリ
	 */
	private String getQuery() {
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT * FROM ").append(this.table).append(" WHERE ");
		boolean and = false;
		for (final String val : this.column) {
			if (and) {
				sb.append(" AND ");
			}
			sb.append(val).append(" = ? ");
			and = true;
		}

		String str = getVersionQuery();
		if (str != null) {
			if (and) {
				sb.append(" AND ");
			}
			sb.append(str);
		}

		return sb.toString();
	}

	/**
	 * バージョンクエリ取得
	 *
	 * @return バージョンクエリ
	 */
	private String getVersionQuery() {
		DBMetaData dmd = Factory.create(DBMetaData.class);
		Map<String, DBColumnInfo> map = dmd.getColumnInfo(this.table);
		if (map.containsKey("VERSION") || map.containsKey("version")) {
			return " VERSION > 0 ";
		}
		return null;
	}
}
